﻿
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include <time.h>
#include<pthread.h>

#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include "sample_comm.h"
#include "hi_mipi_tx.h"

#include <poll.h>
#include <stdint.h>
#include <sys/fcntl.h>


//sample_region.h start
#include <sys/prctl.h>
#include "mpi_snap.h"


#define MSG(args...) printf(args)
#ifdef __HuaweiLite__
#define  RES_BMP  "/sharefs/bmp/"
#else
#define  RES_BMP  "./"
#endif
#define OverlayExMinHandle 20

//sample_region.h end

#define REGION_1 20 //2 region_handle
#define REGION_2 21
#define REGION_3 22
#define REGION_4 23

#define Reg_1 1 //2 region locate
#define Reg_2 2

pthread_t pid_time;
HI_S32 flag_time = HI_FALSE;

VPSS_CROP_INFO_S cropinfo;
float exadd = 0.5;
float mul = 1.0;

    //HI_S32 x = 0, y = 0, z = 0;
    typedef struct
    {
        int x;
        int y;
    }POINT;
    POINT point = { 0, 0 }; //记录在每级菜单上用户的选择行
    typedef struct
    {
        char strings[20]; //contains
        int flag; //flag>100,the color is red
    }MENU;

    /* 一级菜单 */
    MENU menu[3] = {
      {" TIME   ",101},
      {" OPER   ",2},
      {" EXIT   ",3}
    };
    HI_S32 menu_num = 3;

    /* 二级菜单 */
    MENU timemenu[2] = {
      {" AUTO   ",101},
      {" EXIT   ",2}
    };
    HI_S32 time_num = 2;

    MENU oper[5] = {
      {" SNAP   ",101},
      {" VIDEO  ",2},
      {" ZOOM+  ",3},
      {" ZOOM-  ",4},
      {" EXIT   ",5}
    };
    HI_S32 oper_num = 5;

    typedef struct stSAMPLE_USER_VO_CONFIG_S {
        VO_SYNC_INFO_S stSyncInfo;
        VO_USER_INTFSYNC_ATTR_S stUserIntfSyncAttr;
        HI_U32 u32PreDiv;
        HI_U32 u32DevDiv;
        HI_U32 u32Framerate;
        combo_dev_cfg_t stcombo_dev_cfgl;
    }SAMPLE_USER_VO_CONFIG_S;

    HI_VOID SAMPLE_VOU_SYS_Exit(void)
    {
        HI_MPI_SYS_Exit();
        HI_MPI_VB_Exit();
    }

/* 根据倍数决定裁剪属性的设置 */
static VPSS_CROP_INFO_S SETcrop(float mul)
{
	VPSS_CROP_INFO_S   stCropInfo;//声明裁剪属性
	/*config crop*/
	/*X是高（0-500），Y是宽（0-800）*/
	stCropInfo.bEnable = HI_TRUE; //启动裁剪功能
	stCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;//绝对坐标模式
	//高2字节对齐，宽4
	if (mul == 4)
	{
		stCropInfo.stCropRect.s32X = 850;
		stCropInfo.stCropRect.s32Y = 500;
		stCropInfo.stCropRect.u32Width = 900;//648
		stCropInfo.stCropRect.u32Height = 500;//384
	}
	else if (mul ==3.5)
	{
		stCropInfo.stCropRect.s32X = 800;
		stCropInfo.stCropRect.s32Y = 450;
		stCropInfo.stCropRect.u32Width = 1000;//740
		stCropInfo.stCropRect.u32Height = 600;//438
	}
	else if (mul == 3.0)
	{
		stCropInfo.stCropRect.s32X = 700;
		stCropInfo.stCropRect.s32Y = 400;
		stCropInfo.stCropRect.u32Width = 1100;//864
		stCropInfo.stCropRect.u32Height = 700;//512
	}
	else if (mul == 2.5)
	{
		stCropInfo.stCropRect.s32X = 600;
		stCropInfo.stCropRect.s32Y = 350;
		stCropInfo.stCropRect.u32Width = 1300;//1036
		stCropInfo.stCropRect.u32Height = 800;//614
	}
	else if (mul == 2.0)
	{
		stCropInfo.stCropRect.s32X = 500;
		stCropInfo.stCropRect.s32Y = 300;
		stCropInfo.stCropRect.u32Width =1500;//1296
		stCropInfo.stCropRect.u32Height =900;//768
	}
	else if (mul == 1.5)
	{
		stCropInfo.stCropRect.s32X = 400;//X为高
		stCropInfo.stCropRect.s32Y = 250;//Y为宽
		stCropInfo.stCropRect.u32Width =1728;
		stCropInfo.stCropRect.u32Height =1024 ;
	}
	else
	{
		stCropInfo.stCropRect.s32X = 0;
		stCropInfo.stCropRect.s32Y = 0;
		stCropInfo.stCropRect.u32Width = 2592 ;//本身通道大小
		stCropInfo.stCropRect.u32Height = 1536;

	}

	return stCropInfo;
}

/* 在vpss通道0，进行放缩功能
 * vpss组及通道的set enable操作
 */
HI_S32 SAMPLE_CROP()
{
    HI_S32 s32Ret;
    VPSS_GRP           VpssGrp        = 0; //只能创建group0
    VPSS_CHN           VpssChn        = VPSS_CHN0; //channe0
    HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0}; //channel使能
    VPSS_CHN_ATTR_S    stVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];//channel属性

    s32Ret = HI_MPI_VPSS_GetChnAttr(VpssGrp, VpssChn,&stVpssChnAttr);
    if(s32Ret != HI_SUCCESS)
     {
     return s32Ret;
    }
    stVpssChnAttr[VpssChn].u32Depth = 1;
    s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn,&stVpssChnAttr);
    if(s32Ret != HI_SUCCESS)
    {
    return s32Ret;
    }

    s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);
    if(s32Ret != HI_SUCCESS)
    {
    return s32Ret;
    }

    s32Ret = HI_MPI_VPSS_ResetGrp(VpssGrp);
	if (s32Ret != HI_SUCCESS)
	{
        printf("HI_MPI_VPSS_ResetGrp failed\n");
		return s32Ret;
	}
		printf("get the beishu:smul:%f\n", mul);
		printf("width:%d,Height:%d\n", cropinfo.stCropRect.u32Width, cropinfo.stCropRect.u32Height);
		s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &cropinfo);//设置crop属性
		if (s32Ret != HI_SUCCESS)
		{
			printf("not ok");
			return s32Ret;
		}
		printf("end1\n");
		s32Ret = HI_MPI_VPSS_GetGrpCrop(VpssGrp, &cropinfo);//get crop
		if (s32Ret != HI_SUCCESS)
		{
			printf("not ok");
			return s32Ret;
		}
		printf("end the set\n");
}

/* 放大功能 */
HI_S32 SAMPLE_Zoom_in()
{
    HI_S32 s32Ret;
    if(mul > 4.0-exadd) 
    {
        mul = 1.0; //当放大倍数到达4时，不能再放大，返回到1.0
    }
    else mul += exadd;
	cropinfo = SETcrop(mul);
    MSG("mul=%f \n", mul);
    s32Ret = SAMPLE_CROP();
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_CROP zoom in failed!\n");
        return s32Ret;
    }
}

/* 缩小功能 */
HI_S32 SAMPLE_Zoom_out()
{
    HI_S32 s32Ret;
    if(mul < 1.0+exadd) 
    {
        mul = 4.0;//当缩小到1倍时，不能再缩小,返回到4.0
    }
    else mul -= exadd;
	cropinfo=SETcrop(mul);
	MSG("mul=%f \n", mul);
    s32Ret = SAMPLE_CROP();
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_CROP zoom out failed!\n");
        return s32Ret;
    }
}

    /******************************************************************************
    * function: Jpeg,Channel resolution adaptable with sensor
    ******************************************************************************/
   /* 截图功能 */
    HI_S32 SAMPLE_VENC_JPEG(void)
    {
        HI_S32 s32Ret;

        SAMPLE_VI_CONFIG_S stViConfig;
        HI_S32 s32WorkSnsId = 0;
        SIZE_S          stSize;
        PIC_SIZE_E      enSize = PIC_3840x2160;

        HI_S32          s32ChnNum = 1;
        VENC_CHN        VencChn = 1;
        HI_BOOL         bSupportDcf = HI_FALSE; //不需要有缩略图

        VPSS_GRP        VpssGrp = 0;
        VPSS_CHN        VpssChn = 2;
        HI_BOOL         abChnEnable[VPSS_MAX_PHY_CHN_NUM];

        HI_U32 u32SupplementConfig = HI_FALSE;

        abChnEnable[VpssChn] = HI_TRUE;

        VPSS_GRP_ATTR_S stVpssGrpAttr = { 0 };
        VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
        DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
        PIXEL_FORMAT_E     enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;


        //从sensor类型得到图像数据，1080P、720P等
        s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size by sensor failed!\n");
            return s32Ret;
        }

        //从1080P、720P等得到图像的宽和高
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize, &stSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size failed!\n");
            return s32Ret;
        }

        stVpssGrpAttr.enDynamicRange = enDynamicRange;
        stVpssGrpAttr.enPixelFormat = enPixelFormat;
        stVpssGrpAttr.u32MaxW = stSize.u32Width;
        stVpssGrpAttr.u32MaxH = stSize.u32Height;
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssGrpAttr.bNrEn = HI_TRUE;
        stVpssGrpAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
        stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
        stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;


        if (HI_TRUE == abChnEnable[VpssChn])
        {
            stVpssChnAttr[VpssChn].u32Width = stSize.u32Width;
            stVpssChnAttr[VpssChn].u32Height = stSize.u32Height;
            stVpssChnAttr[VpssChn].enChnMode = VPSS_CHN_MODE_USER;
            stVpssChnAttr[VpssChn].enCompressMode = COMPRESS_MODE_NONE;//COMPRESS_MODE_SEG;
            stVpssChnAttr[VpssChn].enDynamicRange = enDynamicRange;
            stVpssChnAttr[VpssChn].enPixelFormat = enPixelFormat;
            stVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
            stVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
            stVpssChnAttr[VpssChn].u32Depth = 0;
            stVpssChnAttr[VpssChn].bMirror = HI_FALSE;
            stVpssChnAttr[VpssChn].bFlip = HI_FALSE;
            stVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR;
            stVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_NONE;
        }

        //start vpss
        if (HI_TRUE == abChnEnable[VpssChn])
        {
            s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stVpssChnAttr[VpssChn]);
            if (s32Ret != HI_SUCCESS)
            {
                 SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr failed with %#x\n", s32Ret);
                return HI_FAILURE;
            }

            s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("HI_MPI_VPSS_EnableChn failed with %#x\n", s32Ret);
                return HI_FAILURE;
            }
        }
        s32Ret = HI_MPI_VPSS_StartGrp(VpssGrp);

        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_VPSS_StartGrp failed with %#x\n", s32Ret);
            return HI_FAILURE;
        }

        /***encode Jpege **/
        s32Ret = SAMPLE_COMM_VENC_SnapStart(VencChn, &stSize, bSupportDcf);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
            goto EXIT_VENC_JPEGE_UnBind;
        }

        s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc bind Vpss failed for %#x!\n", s32Ret);
            goto EXIT_VENC_JPEGE_STOP;
        }

        /******************************************
         stream venc process -- get jpeg stream, then save it to file.
        ******************************************/
        s32Ret = SAMPLE_COMM_VENC_SnapProcess(VencChn, 1, HI_TRUE, HI_FALSE); //bsavejpg = HI_TRUE ; bsavethm = HI_FALSE
        if (HI_SUCCESS != s32Ret)
        {
            printf("%s: sanp process failed!\n", __FUNCTION__);
            return 0;
        }
        printf("snap success!\n"); //成功截图并存入 ./source_file

    EXIT_VENC_JPEGE_UnBind:
        SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn);
    EXIT_VENC_JPEGE_STOP:
        SAMPLE_COMM_VENC_Stop(VencChn);

        return s32Ret;
    }

    //VENC的编码设置为VBR
    SAMPLE_RC_E SAMPLE_VENC_GetRcMode(void)
    {
        SAMPLE_RC_E  enRcMode = 0;
        enRcMode = SAMPLE_RC_VBR;
        return enRcMode;
    }
    VENC_GOP_MODE_E SAMPLE_VENC_GetGopMode(void)
    {
        VENC_GOP_MODE_E enGopMode = 0;
        enGopMode = VENC_GOPMODE_NORMALP;
        return enGopMode;
    }

    /******************************************************************************
    * function: H.265e , H.265 Channel resolution adaptable with sensor
    ******************************************************************************/
    /*H265编码*/
    HI_S32 SAMPLE_VENC_H265(void) 
    {
        HI_S32 i;
        HI_S32 s32Ret;
        SIZE_S          stSize;
        PIC_SIZE_E      enSize = PIC_720P; //视频分辨率
        HI_S32          s32ChnNum = 1; //venc通道数目
        VENC_CHN        VencChn = 0 ;
        HI_U32          u32Profile = 0 ;
        PAYLOAD_TYPE_E  enPayLoad = PT_H265;
        VENC_GOP_MODE_E enGopMode;
        VENC_GOP_ATTR_S stGopAttr;
        SAMPLE_RC_E     enRcMode;
        HI_BOOL         bRcnRefShareBuf = HI_TRUE;

        VI_PIPE         ViPipe = 0;
        VI_CHN          ViChn = 0;
        SAMPLE_VI_CONFIG_S stViConfig;
        HI_S32 s32WorkSnsId = 0;

        VPSS_GRP        VpssGrp = 0;
        VPSS_CHN        VpssChn = 2;
        HI_BOOL         abChnEnable[VPSS_MAX_PHY_CHN_NUM] = { 0 };

        HI_U32 u32SupplementConfig = HI_FALSE;

        abChnEnable[VpssChn] = HI_TRUE;
        VPSS_GRP_ATTR_S stVpssGrpAttr = { 0 };
        VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
        DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
        PIXEL_FORMAT_E     enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

        //从1080P、720P等分辨率得到图像的宽和高
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize, &stSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size failed!\n");
            return s32Ret;
        }

        stVpssGrpAttr.enDynamicRange = enDynamicRange;
        stVpssGrpAttr.enPixelFormat = enPixelFormat;
        stVpssGrpAttr.u32MaxW = stSize.u32Width;
        stVpssGrpAttr.u32MaxH = stSize.u32Height;
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssGrpAttr.bNrEn = HI_TRUE;
        stVpssGrpAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
        stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
        stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;

        for (i = 0; i < VPSS_MAX_PHY_CHN_NUM; i++)
        {
            if (HI_TRUE == abChnEnable[i])
            {
                stVpssChnAttr[i].u32Width = stSize.u32Width;
                stVpssChnAttr[i].u32Height = stSize.u32Height;
                stVpssChnAttr[i].enChnMode = VPSS_CHN_MODE_USER;
                stVpssChnAttr[i].enCompressMode = COMPRESS_MODE_NONE;//COMPRESS_MODE_SEG;
                //stVpssChnAttr[i].enCompressMode = COMPRESS_MODE_SEG; //only chn0支持compress
                stVpssChnAttr[i].enDynamicRange = enDynamicRange;
                stVpssChnAttr[i].enPixelFormat = enPixelFormat;
                stVpssChnAttr[i].stFrameRate.s32SrcFrameRate = -1;
                stVpssChnAttr[i].stFrameRate.s32DstFrameRate = -1;
                stVpssChnAttr[i].u32Depth = 0;
                stVpssChnAttr[i].bMirror = HI_FALSE;
                stVpssChnAttr[i].bFlip = HI_FALSE;
                stVpssChnAttr[i].enVideoFormat = VIDEO_FORMAT_LINEAR; //线性存储的视频格式
                stVpssChnAttr[i].stAspectRatio.enMode = ASPECT_RATIO_NONE;
            }
        }
        HI_S32 j;
        for (j = 0; j < VPSS_MAX_PHY_CHN_NUM; j++)
        {
            if (HI_TRUE == abChnEnable[j])
            {
                VpssChn = j;
                s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stVpssChnAttr[VpssChn]);

                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr failed with %#x\n", s32Ret);
                    return HI_FAILURE;
                }

                s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);

                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("HI_MPI_VPSS_EnableChn failed with %#x\n", s32Ret);
                    return HI_FAILURE;
                }
            }
        }
        s32Ret = HI_MPI_VPSS_StartGrp(VpssGrp);

        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_VPSS_StartGrp failed with %#x\n", s32Ret);
            return HI_FAILURE;
        }

        /******************************************
         start stream venc
         ******************************************/
        enRcMode = SAMPLE_VENC_GetRcMode();
        enGopMode = SAMPLE_VENC_GetGopMode();
        s32Ret = SAMPLE_COMM_VENC_GetGopAttr(enGopMode, &stGopAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Get GopAttr for %#x!\n", s32Ret);
            goto EXIT_VENC_H265_UnBind;
        }

        /***encode h.265 **/
        s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad, enSize, enRcMode, u32Profile, bRcnRefShareBuf, &stGopAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
            goto EXIT_VENC_H265_UnBind;
        }
        s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Get GopAttr failed for %#x!\n", s32Ret);
            goto EXIT_VENC_H265_STOP;
        }

        /******************************************
         stream save process
        ******************************************/
        s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, s32ChnNum);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start Venc failed!\n");
            goto EXIT_VENC_H265_UnBind;
        }

        printf("please press F2 to exit\n");
        gpio_F2(); //按动F2按键,停止视频的编码操作

        /******************************************
         exit process
        ******************************************/
        s32Ret = SAMPLE_COMM_VENC_StopGetStream();

    EXIT_VENC_H265_UnBind:
        SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn);
    EXIT_VENC_H265_STOP:
        SAMPLE_COMM_VENC_Stop(VencChn);
        return s32Ret;
    }

    /* F2按键 */
    void gpio_F2()
    {
       int gpio_F2_fd = -1;
       int ret_F2 = -1;
       char buff_F2[10] = { 0 };
       struct pollfd fds_F2[1];

       gpio_F2_fd = open("/sys/class/gpio/gpio1/value", O_RDONLY);
        if (gpio_F2_fd < 0)
        {
            MSG("Failed to open gpio_F2 !\n");
        }
        fds_F2[0].fd = gpio_F2_fd;
        fds_F2[0].events = POLLPRI;
        
       while(1)
       {
           /* read buffer from the gpio1 */
            ret_F2 = read(gpio_F2_fd, buff_F2, 10);
            if (ret_F2 == -1)
            {
                MSG("gpio_F2 read error\n");
            }
            ret_F2 = poll(fds_F2, 1, 0);
            if (ret_F2 == -1)
            {
                MSG("gpio_F2 poll error\n");
            }
           ret_F2 = lseek(gpio_F2_fd, 0, SEEK_SET);
            if (ret_F2 == -1)
            {
                MSG("gpio_F2 lseek error\n");
            }
           if (fds_F2[0].revents & POLLPRI) // F2
            {
                 MSG("sw2 Pressed \n");
                 return 0;
            }
       }
    }

    /******************************************************************************
    * function: H.264e , H.264 Channel resolution adaptable with sensor
    ******************************************************************************/
   /* 视频进行H264编码 */
    HI_S32 SAMPLE_VENC_H264(void)
    {
        HI_S32 s32Ret;
        SIZE_S          stSize;
        PIC_SIZE_E      enSize = PIC_720P;//视频分辨率
        HI_S32          s32ChnNum = 1; //venc通道数
        VENC_CHN   VencChn = 0; //H264编码的venc通道号
        HI_U32          u32Profile = 0;
        PAYLOAD_TYPE_E  enPayLoad = PT_H264;
        VENC_GOP_MODE_E enGopMode;
        VENC_GOP_ATTR_S stGopAttr;
        SAMPLE_RC_E     enRcMode;
        HI_BOOL         bRcnRefShareBuf = HI_TRUE;

        VI_PIPE         ViPipe = 0;
        VI_CHN          ViChn = 0;
        SAMPLE_VI_CONFIG_S stViConfig;
        HI_S32 s32WorkSnsId = 0;

        VPSS_GRP        VpssGrp = 0;
        VPSS_CHN        VpssChn = 2;
        HI_BOOL         abChnEnable[VPSS_MAX_PHY_CHN_NUM];

        HI_U32 u32SupplementConfig = HI_FALSE;

        abChnEnable[VpssChn] = HI_TRUE;

        VPSS_GRP_ATTR_S stVpssGrpAttr = { 0 };
        VPSS_CHN_ATTR_S stVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];
        DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
        PIXEL_FORMAT_E     enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

        //从1080P、720P等分辨率得到图像的宽和高
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize, &stSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size failed!\n");
            return s32Ret;
        }

        stVpssGrpAttr.enDynamicRange = enDynamicRange;
        stVpssGrpAttr.enPixelFormat = enPixelFormat;
        stVpssGrpAttr.u32MaxW = stSize.u32Width;
        stVpssGrpAttr.u32MaxH = stSize.u32Height;
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssGrpAttr.bNrEn = HI_TRUE;
        stVpssGrpAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
        stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
        stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;


        if (HI_TRUE == abChnEnable[VpssChn])
        {
            stVpssChnAttr[VpssChn].u32Width = stSize.u32Width;
            stVpssChnAttr[VpssChn].u32Height = stSize.u32Height;
            stVpssChnAttr[VpssChn].enChnMode = VPSS_CHN_MODE_USER;
            //stVpssChnAttr[VpssChn].enCompressMode = COMPRESS_MODE_NONE;//COMPRESS_MODE_SEG;
            stVpssChnAttr[VpssChn].enCompressMode = COMPRESS_MODE_NONE;
            stVpssChnAttr[VpssChn].enDynamicRange = enDynamicRange;
            stVpssChnAttr[VpssChn].enPixelFormat = enPixelFormat;
            stVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = -1;
            stVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = -1;
            stVpssChnAttr[VpssChn].u32Depth = 0;
            stVpssChnAttr[VpssChn].bMirror = HI_FALSE;
            stVpssChnAttr[VpssChn].bFlip = HI_FALSE;
            stVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR;
            stVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_NONE;
        }

        if (HI_TRUE == abChnEnable[VpssChn])
        {
            s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stVpssChnAttr[VpssChn]);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr failed with %#x\n", s32Ret);
                return HI_FAILURE;
            }

            s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("HI_MPI_VPSS_EnableChn failed with %#x\n", s32Ret);
                return HI_FAILURE;
            }
        }

        s32Ret = HI_MPI_VPSS_StartGrp(VpssGrp); //开启VPSS组

        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_VPSS_StartGrp failed with %#x\n", s32Ret);
            return HI_FAILURE;
        }

        /******************************************
         start stream venc
         ******************************************/

        enRcMode = SAMPLE_VENC_GetRcMode();
        enGopMode = SAMPLE_VENC_GetGopMode();
        s32Ret = SAMPLE_COMM_VENC_GetGopAttr(enGopMode, &stGopAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Get GopAttr for %#x!\n", s32Ret);
            SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
        }

        /***encode h.264 **/
        s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad, enSize, enRcMode, u32Profile, bRcnRefShareBuf, &stGopAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
            SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
        }

        s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn, VencChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Venc Get GopAttr failed for %#x!\n", s32Ret);
            goto EXIT_VENC_H264_STOP;
        }


        /******************************************
         stream save process
        ******************************************/
        s32Ret = SAMPLE_COMM_VENC_StartGetStream(VencChn, s32ChnNum);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start Venc failed!\n");
            goto EXIT_VENC_H264_UnBind;
        }

       printf("please press F2 to exit\n");
       gpio_F2(); //按动F2按键,停止视频的编码操作

        /******************************************
         exit process
        ******************************************/
        s32Ret = SAMPLE_COMM_VENC_StopGetStream();
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VENC_StopGetStream failed for %#x!\n", s32Ret);
        }
    EXIT_VENC_H264_UnBind:
        SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp, VpssChn, VencChn);
    EXIT_VENC_H264_STOP:
        SAMPLE_COMM_VENC_Stop(VencChn);
        return s32Ret;
    }

    /*
    function: GPIO enable
    pin: gpio number */
    static int gpio_export(int pin)
    {
        char buffer[64] = { 0 };
        int len = -1;
        int fd = -1;

        fd = open("/sys/class/gpio/export", O_WRONLY);
        if (fd < 0)
        {
            MSG("Failed to open export for writing!\n");
            close(fd);
            return(-1);
        }

        len = snprintf(buffer, sizeof(buffer), "%d", pin);
        if (write(fd, buffer, len) < 0)
        {
            MSG("Failed to export gpio!");
            close(fd);
            return -1;
        }

        close(fd);
        return 0;
    }

    /*
        function: GPIO disable
        pin: gpio number
    */
    static int gpio_unexport(int pin)
    {
        char buffer[64] = { 0 };
        int len = -1;
        int fd = -1;

        fd = open("/sys/class/gpio/unexport", O_WRONLY);
        if (fd < 0)
        {
            MSG("Failed to open unexport for writing!\n");
            close(fd);
            return -1;
        }

        len = snprintf(buffer, sizeof(buffer), "%d", pin);
        if (write(fd, buffer, len) < 0)
        {
            MSG("Failed to unexport gpio!");
            close(fd);
            return -1;
        }

        close(fd);
        return 0;
    }

    /*
        function: set gpio direction
        pin: gpio number
        dir: 0-->IN, 1-->OUT
    */
    static int gpio_direction(int pin, int dir)
    {
        static const char dir_str[] = "in\0out";
        char path[64] = { 0 };
        int fd = -1;

        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
        fd = open(path, O_WRONLY);
        if (fd < 0)
        {
            MSG("Failed to open gpio direction for writing!\n");
            close(fd);
            return -1;
        }

        if (write(fd, &dir_str[dir == 0 ? 0 : 3], dir == 0 ? 2 : 3) < 0)
        {
            MSG("Failed to set direction!\n");
            close(fd);
            return -1;
        }

        close(fd);
        return 0;
    }


    // none表示引脚为输入，不是中断引脚
    // rising表示引脚为中断输入，上升沿触发
    // falling表示引脚为中断输入，下降沿触发
    // both表示引脚为中断输入，边沿触发
    // 0-->none, 1-->rising, 2-->falling, 3-->both
    static int gpio_edge(int pin, int edge)
    {
        const char dir_str[] = "none\0rising\0falling\0both";
        char ptr;
        char path[64] = { 0 };
        int fd = -1;

        switch (edge)
        {
        case 0:
            ptr = 0;
            break;
        case 1:
            ptr = 5;
            break;
        case 2:
            ptr = 12;
            break;
        case 3:
            ptr = 20;
            break;
        default:
            ptr = 0;
        }
        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);

        fd = open(path, O_WRONLY);
        if (fd < 0)
        {
            MSG("Failed to open gpio edge for writing!\n");
            close(fd);
            return -1;
        }

        if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0)
        {
            MSG("Failed to set edge!\n");
            close(fd);
            return -1;
        }

        close(fd);
        return 0;
    }

   /* 控制菜单光标下移 */
    int scroll_down(MENU* menu, HI_S32 num)
    {
        int i;
        for (i = 0;; i++)
        {
            if (menu[i].flag > 100)
            {
                menu[i].flag -= 100;
                if (i == num - 1)
                {
                    menu[0].flag += 100; //next line is red
                    i = -1;
                }
                else menu[i + 1].flag += 100;
                return i + 1;
            }
        }
    }

    /* 菜单退出功能，实现菜单所在级复原 */
    void exit_func(MENU* menu, HI_S32 num)
    {
        menu[0].flag += 100;
        menu[num - 1].flag -= 100;
    }

    /*某一级菜单的OSD显示*/
    void looking(MENU* menu, HI_S32 num, HI_S32 Handle)
    {
        HI_S32         i;
        BITMAP_S     stBitmap;
        TTF_Font* font;
        SDL_PixelFormat* fmt;
        SDL_Surface* screen;
        SDL_Color red_forecol = { 0x80, 0xff, 0xff, 0xff };

        if (TTF_Init() < 0)
        {
            fprintf(stderr, "Couldn't initialize TTF:%s\n", SDL_GetError());
            SDL_Quit();
        }
        font = TTF_OpenFont("/usr/share/fonts/simhei.ttf", 60);
        if (NULL == font)
        {
            fprintf(stderr, "Couldn't load %d pt font from %s:%s\n", 60, "ptsize", SDL_GetError());
        }

        SDL_Color forecol[6] =
        {

        { 0xff, 0xff, 0xff, 0xff },

        { 0xff, 0xff, 0xff, 0xff },

        { 0xff, 0xff, 0xff, 0xff },

        { 0xff, 0xff, 0xff, 0xff },

        { 0xff, 0xff, 0xff, 0xff },

        { 0xff, 0xff, 0xff, 0xff }

        };
        fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
        memset(fmt, 0, sizeof(SDL_PixelFormat));
        fmt->BitsPerPixel = 16;
        fmt->BytesPerPixel = 2;
        fmt->colorkey = 0xffffffff;
        fmt->alpha = 0xff;

        screen = (struct SDL_Surface*)malloc(sizeof(struct SDL_Surface));
        //screen->pixels = malloc(30 * 61 *5);
        screen->pixels = malloc(30 *61 * 3);
        //screen->pixels = malloc(6*1024);
        //memset(screen->pixels, 0, sizeof(screen->pixels));

        for (i = 0; i < num; i++)
        {
            SDL_Surface* text;
            SDL_Surface* temp;
            //temp = (struct SDL_Surface*)malloc(sizeof(struct SDL_Surface));
            text = (struct SDL_Surface*)malloc(sizeof(struct SDL_Surface));
            //text->pixels = malloc(10 * 61);
            
            if (menu[i].flag > 100) {
                forecol[i] = red_forecol;
            }

            temp = TTF_RenderText_Solid(font, menu[i].strings, forecol[i]);

            text = SDL_ConvertSurface(temp, fmt, 0x00);

            SDL_FreeSurface(temp);

            screen->w = text->w;
            screen->h = (text->h) * (i + 1);
            memcpy((&(screen->pixels)) + (sizeof(text->pixels)) * i, &(text->pixels), sizeof(text->pixels));
            free(text);
        }
        stBitmap.u32Width = screen->w;
        stBitmap.u32Height = screen->h;
        stBitmap.pData = screen->pixels;
        stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555;

        SAMPLE_REGION_SetBitMap(Handle, &stBitmap);

        free(screen);
        TTF_CloseFont(font);
        TTF_Quit();
    }

    /* 菜单显示 */
    void Look(MENU* menu, HI_S32 num, HI_S32 Handle, MPP_CHN_S* pstChn)
    {
        SAMPLE_COMM_REGION_Show(Handle, pstChn); //菜单所在区域显示
        looking(menu, num, Handle);
    }

    /* 实现按键F1控制菜单光标下移*/
    int menu_turn(MENU* menu, HI_S32 num, HI_S32 Handle, MPP_CHN_S* pstChn)
    {
        int ret;
        ret = scroll_down(menu, num);
        Look(menu, num, Handle, pstChn);
        return ret;
    }

    /* Initialization key 1*/
    void init_gpio1(void)
    {
        MSG("\n =============== init_gpio1 start ========== \n");
        gpio_unexport(1);
        gpio_export(1);
        gpio_direction(1, 0);
        gpio_edge(1, 2);
        MSG("\n =============== init_gpio1 end ========== \n");
    }

    /* Initialization key 2*/
    void init_gpio2(void)
    {
        MSG("\n =============== init_gpio2 start ========== \n");
        gpio_unexport(2);
        gpio_export(2);
        gpio_direction(2, 0);
        gpio_edge(2, 2);
        MSG("\n =============== init_gpio2 end ========== \n");
    }

    // 一级菜单menu所列功能的选择
    int menu_select(MPP_CHN_S* pstChn)
    {
        HI_S32 select;
        select = menu_turn(menu, menu_num, REGION_1, pstChn);
        return select;
    }

    //二级菜单time所列功能的选择
    int time_select(MPP_CHN_S* pstChn)
    {
        HI_S32 select;
        select = menu_turn(timemenu, time_num, REGION_2, pstChn);
        return select;
    }
   
    //二级菜单oper所列功能的选择
    int oper_select(MPP_CHN_S* pstChn)  //other_select
    {
        HI_S32 select;
        select = menu_turn(oper, oper_num, REGION_2, pstChn);
        return select;
    }

    /* 当前时间的显示 */
    void* TIME_Show(void* arg)
    {
        pid_time = pthread_self();
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
        while (1)
        {
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
            BITMAP_S     stBitmap;
            TTF_Font* font;
            SDL_PixelFormat* fmt;

            char cur_time[20] = { 0 };
            time_t tt;
            time(&tt);     //obtain seconds
            struct tm* p;
            p = gmtime(&tt);
            snprintf(cur_time, 20, "%d-%d-%d %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);

            printf("current time: %s", cur_time);

            if (TTF_Init() < 0)
            {
                fprintf(stderr, "Couldn't initialize TTF:%s\n", SDL_GetError());
                SDL_Quit();
            }
            font = TTF_OpenFont("/usr/share/fonts/simhei.ttf", 60);
            if (NULL == font)
            {
                fprintf(stderr, "Couldn't load %d pt font from %s:%s\n", 60, "ptsize", SDL_GetError());
            }

            SDL_Color forecol = { 0xff, 0xff, 0xff, 0xff };

            fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
            memset(fmt, 0, sizeof(SDL_PixelFormat));
            fmt->BitsPerPixel = 16;
            fmt->BytesPerPixel = 2;
            fmt->colorkey = 0xffffffff;
            fmt->alpha = 0xff;

            SDL_Surface* text;
            SDL_Surface* temp;
            //temp = (struct SDL_Surface*)malloc(sizeof(struct SDL_Surface));
            //text = (struct SDL_Surface*)malloc(sizeof(struct SDL_Surface));

            temp = TTF_RenderText_Solid(font, cur_time, forecol);
            //text->pixels = (void*)malloc((temp->h) * (temp->w) * 2);
            text = SDL_ConvertSurface(temp, fmt, 0x00);
            SDL_FreeSurface(temp);

            stBitmap.u32Width = text->w;
            stBitmap.u32Height = text->h;
            stBitmap.pData = text->pixels;
            stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555;

            SAMPLE_REGION_SetBitMap(REGION_3, &stBitmap);

            SDL_FreeSurface(text);
            TTF_CloseFont(font);
            TTF_Quit();
            usleep(1000000); // 每隔1s刷新时间

            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
            pthread_testcancel();
        }
    }

    /* 显示时间的OSD的隐藏 */
    void TIME_Hide(MPP_CHN_S* pstChn)
    {
        SAMPLE_COMM_REGION_Hide(REGION_3, pstChn);
    }

    /* 放缩倍数的OSD显示 */
    void Zoom_Show(float ret_mul)
    {
        BITMAP_S     stBitmap;
        TTF_Font* font;
        SDL_PixelFormat* fmt;

        SDL_Surface* text;
        SDL_Surface* temp;
        if (TTF_Init() < 0)
        {
            fprintf(stderr, "Couldn't initialize TTF:%s\n", SDL_GetError());
            SDL_Quit();
        }
        font = TTF_OpenFont("/usr/share/fonts/simhei.ttf", 60);
        if (NULL == font)
        {
            fprintf(stderr, "Couldn't load %d pt font from %s:%s\n", 60, "ptsize", SDL_GetError());
        }

        SDL_Color forecol = { 0xff, 0xff, 0xff, 0xff };

        fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
        memset(fmt, 0, sizeof(SDL_PixelFormat));
        fmt->BitsPerPixel = 16;
        fmt->BytesPerPixel = 2;
        fmt->colorkey = 0xffffffff;
        fmt->alpha = 0xff;

        char zoom_mul[30] = { 0 };
        snprintf(zoom_mul, 30, "ZOOM MUL * %.1f", ret_mul);
        printf("ZOOM MUL* %.1f\n",ret_mul);

        temp = TTF_RenderText_Solid(font, zoom_mul, forecol);
        text = SDL_ConvertSurface(temp, fmt, 0x00);
        
        stBitmap.u32Width = text->w;
        stBitmap.u32Height = text->h;
        stBitmap.pData = text->pixels;
        stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555;

        SAMPLE_REGION_SetBitMap(REGION_4, &stBitmap);

        SDL_FreeSurface(temp);
        SDL_FreeSurface(text);
        TTF_CloseFont(font);
        TTF_Quit();
    }

    /* 放缩倍数的OSD隐藏 */
    void Zoom_Hide(MPP_CHN_S* pstChn)
    {
        SAMPLE_COMM_REGION_Hide(REGION_4, pstChn);
    }

    //一级菜单menu所列功能实现
    int first_menu(int a, HI_S32 Reg, MPP_CHN_S* pstChn)
    {
        switch (a)
        {
        case 0:
            Look(timemenu, time_num, REGION_2, pstChn); //显示二级菜单time
            Reg = Reg_2;
            break;
        case 1: 
            Look(oper, oper_num, REGION_2, pstChn); //显示二级菜单oper
            Reg = Reg_2;
            break;
        case 2: //一级菜单上的退出
            SAMPLE_COMM_REGION_Hide(REGION_1, pstChn); //隐藏一级菜单
            Zoom_Hide(pstChn); 
            break;
        }
        return Reg;
    }
    
    //二级菜单time所列功能实现
    int time_menu(int a, HI_S32 Reg, MPP_CHN_S* pstChn)		//setting_menu
    {
        switch (a)
        {
        case 0: //实现时间的显示及隐藏
            printf("Auto over\r\n");
            if (flag_time == HI_FALSE)
            {
                pthread_t id1;
                pthread_create(&id1, NULL, (void*)TIME_Show, NULL);
                SAMPLE_COMM_REGION_Show(REGION_3, pstChn);
                flag_time = HI_TRUE;
            }
            else
            {
                TIME_Hide(pstChn);
                pthread_cancel(pid_time);
                pthread_join(pid_time, NULL);
                flag_time = HI_FALSE;
            }
            Reg = Reg_2;
            break;
        case 1:
            printf("exit! \n");
            exit_func(timemenu, time_num);
            SAMPLE_COMM_REGION_Hide(REGION_2, pstChn);
            Reg = Reg_1;
            break;
        }
        return Reg;
    }
   
    //二级菜单oper所列功能的实现
    int oper_menu(int a, HI_S32 Reg, MPP_CHN_S* pstChn)
    {
        float ret_mul = 0.0;
        switch (a)
        {
        case 0:
            SAMPLE_VENC_JPEG(); //截图功能实现
            printf("SNAP over\r\n");
            break;
        case 1:
            SAMPLE_VENC_H265(); //视频h265编码实现，并以265格式保存在/source_file
            printf("VIDEO over\r\n");
            break;
        case 2: //实现图像放大功能
            SAMPLE_Zoom_in(); 
            if(mul < 1) ret_mul = 4.0;
            else ret_mul = mul;
            Zoom_Show(ret_mul);
            SAMPLE_COMM_REGION_Show(REGION_4, pstChn);
            printf("zoom in success\r\n");
            break;
        case 3: //实现图像缩小功能
            SAMPLE_Zoom_out(); 
            if(mul > 4) ret_mul = 1.0;
            else ret_mul = mul;
            Zoom_Show(ret_mul);
            SAMPLE_COMM_REGION_Show(REGION_4, pstChn);
            printf("zoom out success\r\n");
            break;
        case 4: //退出二级菜单oper,返回到一级菜单
            exit_func(oper, oper_num);
            SAMPLE_COMM_REGION_Hide(REGION_2, pstChn);
            Reg = Reg_1;
            break;
        }
        return Reg;
    }

    /* 按键 F1/F2 控制菜单 */
    int gpio(MPP_CHN_S* pstChn) //F2-->gpio1 F1-->gpio2
    {
        
        int gpio1_fd = -1;
        int gpio2_fd = -1;
        int ret1 = -1;
        int ret2 = -1;
        char buff[10] = { 0 };
        struct pollfd fds1[1];
        struct pollfd fds2[1];
        
        HI_S32 Reg = 1;

        /* init key1 and key2 */
        init_gpio1();
        init_gpio2();

        gpio1_fd = open("/sys/class/gpio/gpio1/value", O_RDONLY);
        if (gpio1_fd < 0)
        {
            MSG("Failed to open gpio1 !\n");
        }
        fds1[0].fd = gpio1_fd;
        fds1[0].events = POLLPRI;

        gpio2_fd = open("/sys/class/gpio/gpio2/value", O_RDONLY);
        if (gpio2_fd < 0)
        {
            MSG("Failed to open gpio1 !\n");
        }
        fds2[0].fd = gpio2_fd;
        fds2[0].events = POLLPRI;

        while (1)
        {
            /* read buffer from the gpio2 */
            ret2 = read(gpio2_fd, buff, 10);
            if (ret2 == -1)
            {
                MSG("gpio2 read error\n");
            }

            ret2 = poll(fds2, 1, 0);
            if (ret2 == -1)
            {
                MSG("gpio2 poll error\n");
            }

            if (fds2[0].revents & POLLPRI) // F1按键
            {
                ret2 = lseek(gpio2_fd, 0, SEEK_SET);
                if (ret2 == -1)
                {
                    MSG("gpio1 lseek error\n");
                }
                if (Reg == 1) //菜单为一级菜单
                {
                    point.x = menu_select(pstChn); //一级菜单上,控制按键选择某一行功能;point.x记录下用户选择的行数
                }
                else if (Reg == 2) //菜单为二级菜单
                {
                    switch (point.x) //在一级菜单上,用户选择后被记录下的行数
                    {
                    case 0:
                        point.y = time_select(pstChn); //进入二级菜单time
                        break;
                    case 1:
                        point.y = oper_select(pstChn); //进入二级菜单oper
                        break;
                    }
                }
                MSG("sw1 Pressed \n");
            }

            /* read buffer from the gpio1 */
            ret1 = read(gpio1_fd, buff, 10);
            if (ret1 == -1)
            {
                MSG("gpio1 read error\n");
            }

            ret1 = poll(fds1, 1, 0);
            if (ret1 == -1)
            {
                MSG("gpio1 poll error\n");
            }

            if (fds1[0].revents & POLLPRI) // F2按键
            {
                ret1 = lseek(gpio1_fd, 0, SEEK_SET);
                if (ret1 == -1)
                {
                    MSG("gpio1 lseek error\n");
                }

                if (Reg == Reg_1) //菜单为一级菜单
                {
                    Reg = first_menu(point.x, Reg, pstChn); //根据用户在一级菜单选择的某行,执行相应功能
                    if (point.x == menu_num - 1) //在一级菜单中选择exit
                    {
                        printf("exit menu\n");
                        return 0;
                    }
                }
                else if (Reg == Reg_2) //菜单为二级菜单
                {
                    switch (point.x)
                    {
                    case 0:
                        Reg = time_menu(point.y, Reg, pstChn); //根据用户在二级菜单time中选择的某行,执行相应功能
                        if (point.y == time_num - 1) //在二级菜单time中选择exit
                        {
                            printf("exit time\n");
                            point.y = 0;
                            printf("point.y = 0 \n");
                        }
                        break;
                    case 1:
                        Reg = oper_menu(point.y, Reg, pstChn); //根据用户在二级菜单oper中选择的某行,执行相应功能
                        if (point.y == oper_num - 1) //在二级菜单oper中选择exit
                        {
                            printf("exit other\n");
                            point.y = 0;
                            printf("point.y = 0 \n");
                        }
                        break;
                    }
                }
                MSG("sw2 Pressed \n");
            }

            usleep(5);
        }

        return 0;
    }

    HI_VOID SAMPLE_VO_GetUserLayerAttr(VO_VIDEO_LAYER_ATTR_S* pstLayerAttr, SIZE_S* pstDevSize)
    {
        pstLayerAttr->bClusterMode = HI_FALSE;
        pstLayerAttr->bDoubleFrame = HI_FALSE;
        pstLayerAttr->enDstDynamicRange = DYNAMIC_RANGE_SDR8;
        pstLayerAttr->enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

        pstLayerAttr->stDispRect.s32X = 0;
        pstLayerAttr->stDispRect.s32Y = 0;
        pstLayerAttr->stDispRect.u32Height = pstDevSize->u32Height;
        pstLayerAttr->stDispRect.u32Width = pstDevSize->u32Width;

        pstLayerAttr->stImageSize.u32Height = pstDevSize->u32Height;
        pstLayerAttr->stImageSize.u32Width = pstDevSize->u32Width;

        return;
    }

    HI_VOID SAMPLE_VO_GetUserChnAttr(VO_CHN_ATTR_S* pstChnAttr, SIZE_S* pstDevSize, HI_S32 VoChnNum)
    {
        HI_S32 i;
        for (i = 0; i < VoChnNum; i++) {
            pstChnAttr[i].bDeflicker = HI_FALSE;
            pstChnAttr[i].u32Priority = 0;
            pstChnAttr[i].stRect.s32X = 0;
            pstChnAttr[i].stRect.s32Y = 0;
            pstChnAttr[i].stRect.u32Height = pstDevSize->u32Height;
            pstChnAttr[i].stRect.u32Width = pstDevSize->u32Width;
        }

        return;
    }

    /* open mipi_tx device */
    HI_S32 SAMPLE_OPEN_MIPITx_FD(HI_VOID)
    {
        HI_S32 fd;

        fd = open("/dev/hi_mipi_tx", O_RDWR);
        if (fd < 0) {
            printf("open hi_mipi_tx dev failed\n");
        }
        return fd;
    }

    /* close mipi_tx device */
    HI_VOID SAMPLE_CLOSE_MIPITx_FD(HI_S32 fd)
    {
        close(fd);
        return;
    }

    /* get mipi tx config information */
    HI_VOID SAMPLE_GetMipiTxConfig(combo_dev_cfg_t* pstMipiTxConfig)
    {
        /* USER NEED SET MIPI DEV CONFIG */
        pstMipiTxConfig->devno = 0;
        pstMipiTxConfig->lane_id[0] = 0;
        pstMipiTxConfig->lane_id[1] = 1;
        pstMipiTxConfig->lane_id[2] = -1;
        pstMipiTxConfig->lane_id[3] = -1;
        pstMipiTxConfig->output_mode = OUTPUT_MODE_DSI_VIDEO;
        pstMipiTxConfig->output_format = OUT_FORMAT_RGB_24_BIT;
        pstMipiTxConfig->video_mode = BURST_MODE;
        pstMipiTxConfig->sync_info.vid_pkt_size = 480;
        pstMipiTxConfig->sync_info.vid_hsa_pixels = 10;
        pstMipiTxConfig->sync_info.vid_hbp_pixels = 50;
        pstMipiTxConfig->sync_info.vid_hline_pixels = 590;
        pstMipiTxConfig->sync_info.vid_vsa_lines = 4;
        pstMipiTxConfig->sync_info.vid_vbp_lines = 20;
        pstMipiTxConfig->sync_info.vid_vfp_lines = 20;
        pstMipiTxConfig->sync_info.vid_active_lines = 800;
        pstMipiTxConfig->sync_info.edpi_cmd_size = 0;
        pstMipiTxConfig->phy_data_rate = 359;
        pstMipiTxConfig->pixel_clk = 29878;

        return;
    }

    /* set mipi tx config information */
    HI_S32 SAMPLE_SetMipiTxConfig(HI_S32 fd, combo_dev_cfg_t* pstMipiTxConfig)
    {
        HI_S32 s32Ret;
        s32Ret = ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, pstMipiTxConfig);
        if (s32Ret != HI_SUCCESS) {
            printf("MIPI_TX SET_DEV_CONFIG failed\n");
            SAMPLE_CLOSE_MIPITx_FD(fd);
            return s32Ret;
        }
        return s32Ret;
    }

    /* set mipi tx device config */
    HI_S32 SAMPLE_SET_MIPITx_Dev_ATTR(HI_S32 fd)
    {
        HI_S32 s32Ret;
        combo_dev_cfg_t stMipiTxConfig;

        /* USER SET MIPI DEV CONFIG */
        SAMPLE_GetMipiTxConfig(&stMipiTxConfig);

        /* USER SET MIPI DEV CONFIG */
        s32Ret = SAMPLE_SetMipiTxConfig(fd, &stMipiTxConfig);

        return s32Ret;
    }

    /* init mipi tx device */
    HI_S32 SAMPLE_USER_INIT_MIPITx(HI_S32 fd, cmd_info_t* pcmd_info)
    {
        HI_S32 s32Ret;

        s32Ret = ioctl(fd, HI_MIPI_TX_SET_CMD, pcmd_info);
        if (s32Ret != HI_SUCCESS) {
            printf("MIPI_TX SET CMD failed\n");
            SAMPLE_CLOSE_MIPITx_FD(fd);
            return s32Ret;
        }

        return HI_SUCCESS;
    }

    /* set mipi tx device init screen */
    static unsigned char m_buf[50];
    HI_S32 SAMPLE_VO_INIT_MIPITx_Screen(HI_S32 fd)
    {
        HI_S32 s32Ret;
        cmd_info_t cmd_info;
        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x13;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        // memset(m_buf, 0, 50);
        // m_buf[0] = 0xEF; m_buf[1] = 0x08;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x08ef;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x10;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xC0; m_buf[1] = 0x63; m_buf[2] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xC1; m_buf[1] = 0x10; m_buf[2] = 0x02;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xC2; m_buf[1] = 0x01; m_buf[2] = 0x08;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x18CC;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xB0; m_buf[1] = 0x40; m_buf[2] = 0xC9; m_buf[3] = 0x8F; m_buf[4] = 0x0D; m_buf[5] = 0x11; m_buf[6] = 0x07; m_buf[7] = 0x02;
        m_buf[8] = 0x09; m_buf[9] = 0x09; m_buf[10] = 0x1F; m_buf[11] = 0x04; m_buf[12] = 0x50; m_buf[13] = 0x0F; m_buf[14] = 0xE4; m_buf[15] = 0x29; m_buf[16] = 0xDF;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 17;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xB1; m_buf[1] = 0x40; m_buf[2] = 0xCB; m_buf[3] = 0xD3; m_buf[4] = 0x11; m_buf[5] = 0x8F; m_buf[6] = 0x04; m_buf[7] = 0x00;
        m_buf[8] = 0x08; m_buf[9] = 0x07; m_buf[10] = 0x1C; m_buf[11] = 0x06; m_buf[12] = 0x53; m_buf[13] = 0x12; m_buf[14] = 0x63; m_buf[15] = 0xEB; m_buf[16] = 0xDF;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 17;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x11;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x65b0;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x34b1;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x87b2;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x80b3;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x49b5;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x85b7;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x20b8;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x10b9;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x78c1;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x78c2;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x88d0;
        cmd_info.data_type = 0x23;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(100000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE0; m_buf[1] = 0x00; m_buf[2] = 0x19; m_buf[3] = 0x02;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 4;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE1; m_buf[1] = 0x05; m_buf[2] = 0xA0; m_buf[3] = 0x07; m_buf[4] = 0xA0; m_buf[5] = 0x04;
        m_buf[6] = 0xA0; m_buf[7] = 0x06;  m_buf[8] = 0xA0; m_buf[9] = 0x00; m_buf[10] = 0x44; m_buf[11] = 0x44;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 12;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE2; m_buf[1] = 0x00; m_buf[2] = 0x00; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x00; m_buf[6] = 0x00;
        m_buf[7] = 0x00;  m_buf[8] = 0x00; m_buf[9] = 0x00; m_buf[10] = 0x00; m_buf[11] = 0x00; m_buf[12] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 13;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE3; m_buf[1] = 0x00; m_buf[2] = 0x00; m_buf[3] = 0x33; m_buf[4] = 0x33;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 5;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE4; m_buf[1] = 0x44; m_buf[2] = 0x44;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE5; m_buf[1] = 0x0D; m_buf[2] = 0x31; m_buf[3] = 0xC8; m_buf[4] = 0xAF; m_buf[5] = 0x0F; m_buf[6] = 0x33; m_buf[7] = 0xC8;
        m_buf[8] = 0xAF; m_buf[9] = 0x09; m_buf[10] = 0x2D; m_buf[11] = 0xC8; m_buf[12] = 0xAF; m_buf[13] = 0x0B; m_buf[14] = 0x2F; m_buf[15] = 0xC8; m_buf[16] = 0xAF;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 17;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE6; m_buf[1] = 0x00; m_buf[2] = 0x00; m_buf[3] = 0x33; m_buf[4] = 0x33;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 5;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE7; m_buf[1] = 0x44; m_buf[2] = 0x44;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE8; m_buf[1] = 0x0C; m_buf[2] = 0x30; m_buf[3] = 0xC8; m_buf[4] = 0xAF; m_buf[5] = 0x0E; m_buf[6] = 0x32; m_buf[7] = 0xC8;
        m_buf[8] = 0xAF; m_buf[9] = 0x08; m_buf[10] = 0x2C; m_buf[11] = 0xC8; m_buf[12] = 0xAF; m_buf[13] = 0x0A; m_buf[14] = 0x2E; m_buf[15] = 0xC8; m_buf[16] = 0xAF;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 17;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xEB; m_buf[1] = 0x02; m_buf[2] = 0x00; m_buf[3] = 0xE4; m_buf[4] = 0xE4; m_buf[5] = 0x44; m_buf[6] = 0x00; m_buf[7] = 0x40;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 8;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xEC; m_buf[1] = 0x3C; m_buf[2] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xED; m_buf[1] = 0xAB; m_buf[2] = 0x89; m_buf[3] = 0x76; m_buf[4] = 0x54; m_buf[5] = 0x01; m_buf[6] = 0xFF; m_buf[7] = 0xFF;
        m_buf[8] = 0xFF; m_buf[9] = 0xFF; m_buf[10] = 0xFF; m_buf[11] = 0xFF; m_buf[12] = 0x10; m_buf[13] = 0x45; m_buf[14] = 0x67; m_buf[15] = 0x98; m_buf[16] = 0xBA;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 17;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xEF; m_buf[1] = 0x08; m_buf[2] = 0x08; m_buf[3] = 0x08; m_buf[4] = 0x45; m_buf[5] = 0x3F; m_buf[6] = 0x54;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 7;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x13;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE8; m_buf[1] = 0x00; m_buf[2] = 0x0E; m_buf[3] = 0x11;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 4;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(120000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE8; m_buf[1] = 0x00; m_buf[2] = 0x0C;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(10000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xE8; m_buf[1] = 0x00; m_buf[2] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 3;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(10000);

        memset(m_buf, 0, 50);
        m_buf[0] = 0xFF; m_buf[1] = 0x77; m_buf[2] = 0x01; m_buf[3] = 0x00; m_buf[4] = 0x00; m_buf[5] = 0x00;
        cmd_info.devno = 0;
        cmd_info.cmd_size = 6;
        cmd_info.data_type = 0x29;
        cmd_info.cmd = m_buf;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(10000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x11;
        cmd_info.data_type = 0x05;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(150000);

        cmd_info.devno = 0;
        cmd_info.cmd_size = 0x29;
        cmd_info.data_type = 0x05;
        cmd_info.cmd = NULL;
        s32Ret = SAMPLE_USER_INIT_MIPITx(fd, &cmd_info);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }
        usleep(1000);
        usleep(50000);

        return HI_SUCCESS;
    }

    /* enable mipi tx */
    HI_S32 SAMPLE_VO_ENABLE_MIPITx(HI_S32 fd)
    {
        HI_S32 s32Ret;

        s32Ret = ioctl(fd, HI_MIPI_TX_ENABLE);
        if (s32Ret != HI_SUCCESS) {
            printf("MIPI_TX enable failed\n");
            return s32Ret;
        }

        return s32Ret;
    }

    /* disable mipi tx */
    HI_S32 SAMPLE_VO_DISABLE_MIPITx(HI_S32 fd)
    {
        HI_S32 s32Ret;
        s32Ret = ioctl(fd, HI_MIPI_TX_DISABLE);
        if (s32Ret != HI_SUCCESS) {
            printf("MIPI_TX disable failed\n");
            return s32Ret;
        }

        return s32Ret;
    }

    /* config mipi */
    HI_S32 SAMPLE_VO_CONFIG_MIPI(HI_S32* mipiFD)
    {
        HI_S32 s32Ret;
        /* SET MIPI BAKCLIGHT */
        HI_S32  fd;
        /* CONFIG MIPI PINUMX */

        /* Reset MIPI */
        /* OPEN MIPI FD */
        fd = SAMPLE_OPEN_MIPITx_FD();
        if (fd < 0) {
            return HI_FAILURE;
        }
        *mipiFD = fd;

        /* SET MIPI Tx Dev ATTR */
        s32Ret = SAMPLE_SET_MIPITx_Dev_ATTR(fd);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }

        usleep(10000);
        system("cd /sys/class/gpio/;echo 5 > export;echo out > gpio5/direction;echo 1 > gpio5/value");
        usleep(200000);
        system("echo 0 > /sys/class/gpio/gpio5/value");
        usleep(200000);
        system("echo 1 > /sys/class/gpio/gpio5/value");
        usleep(20000);

        /* CONFIG MIPI Tx INITIALIZATION SEQUENCE */
        s32Ret = SAMPLE_VO_INIT_MIPITx_Screen(fd);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }

        /* ENABLE MIPI Tx DEV */
        s32Ret = SAMPLE_VO_ENABLE_MIPITx(fd);
        if (s32Ret != HI_SUCCESS) {
            return s32Ret;
        }

        return s32Ret;
    }

    /* get mipi device Height and width */
    HI_S32 SAMPLE_COMM_VO_GetWH_MIPI(VO_INTF_SYNC_E enIntfSync, HI_U32* pu32W, HI_U32* pu32H, HI_U32* pu32Frm)
    {
        switch (enIntfSync)
        {
        case VO_OUTPUT_PAL:
            *pu32W = 720;
            *pu32H = 576;
            *pu32Frm = 25;
            break;
        case VO_OUTPUT_NTSC:
            *pu32W = 720;
            *pu32H = 480;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_1080P24:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 24;
            break;
        case VO_OUTPUT_1080P25:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 25;
            break;
        case VO_OUTPUT_1080P30:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_720P50:
            *pu32W = 1280;
            *pu32H = 720;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_720P60:
            *pu32W = 1280;
            *pu32H = 720;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1080I50:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_1080I60:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1080P50:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_1080P60:
            *pu32W = 1920;
            *pu32H = 1080;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_576P50:
            *pu32W = 720;
            *pu32H = 576;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_480P60:
            *pu32W = 720;
            *pu32H = 480;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_800x600_60:
            *pu32W = 800;
            *pu32H = 600;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1024x768_60:
            *pu32W = 1024;
            *pu32H = 768;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1280x1024_60:
            *pu32W = 1280;
            *pu32H = 1024;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1366x768_60:
            *pu32W = 1366;
            *pu32H = 768;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1440x900_60:
            *pu32W = 1440;
            *pu32H = 900;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1280x800_60:
            *pu32W = 1280;
            *pu32H = 800;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1600x1200_60:
            *pu32W = 1600;
            *pu32H = 1200;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1680x1050_60:
            *pu32W = 1680;
            *pu32H = 1050;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1920x1200_60:
            *pu32W = 1920;
            *pu32H = 1200;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_640x480_60:
            *pu32W = 640;
            *pu32H = 480;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_960H_PAL:
            *pu32W = 960;
            *pu32H = 576;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_960H_NTSC:
            *pu32W = 960;
            *pu32H = 480;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1920x2160_30:
            *pu32W = 1920;
            *pu32H = 2160;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_2560x1440_30:
            *pu32W = 2560;
            *pu32H = 1440;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_2560x1600_60:
            *pu32W = 2560;
            *pu32H = 1600;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_3840x2160_30:
            *pu32W = 3840;
            *pu32H = 2160;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_3840x2160_60:
            *pu32W = 3840;
            *pu32H = 2160;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_320x240_60:
            *pu32W = 320;
            *pu32H = 240;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_320x240_50:
            *pu32W = 320;
            *pu32H = 240;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_240x320_50:
            *pu32W = 240;
            *pu32H = 320;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_240x320_60:
            *pu32W = 240;
            *pu32H = 320;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_800x600_50:
            *pu32W = 800;
            *pu32H = 600;
            *pu32Frm = 50;
            break;
        case VO_OUTPUT_720x1280_60:
            *pu32W = 720;
            *pu32H = 1280;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_1080x1920_60:
            *pu32W = 1080;
            *pu32H = 1920;
            *pu32Frm = 60;
            break;
        case VO_OUTPUT_7680x4320_30:
            *pu32W = 7680;
            *pu32H = 4320;
            *pu32Frm = 30;
            break;
        case VO_OUTPUT_USER:
            *pu32W = 800;
            *pu32H = 480;
            *pu32Frm = 60;
            break;
        default:
            SAMPLE_PRT("vo enIntfSync %d not support!\n", enIntfSync);
            return HI_FAILURE;
        }

        return HI_SUCCESS;
    }

    HI_S32 SAMPLE_COMM_VO_StartDev_MIPI(VO_DEV VoDev, VO_PUB_ATTR_S* pstPubAttr)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        VO_USER_INTFSYNC_INFO_S stUserInfo = { 0 };

        stUserInfo.bClkReverse = HI_TRUE;
        stUserInfo.u32DevDiv = 1;
        stUserInfo.u32PreDiv = 1;
        stUserInfo.stUserIntfSyncAttr.enClkSource = VO_CLK_SOURCE_PLL;
        stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Fbdiv = 244;
        stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Frac = 0x1A36;
        stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Refdiv = 4;
        stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv1 = 7;
        stUserInfo.stUserIntfSyncAttr.stUserSyncPll.u32Postdiv2 = 7;

        HI_U32 u32Framerate = 60;

        /* Set the common properties of the video output device */
        s32Ret = HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

        /* Set the device frame rate under the device user timing */
        s32Ret = HI_MPI_VO_SetDevFrameRate(VoDev, u32Framerate);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

        /* Set user interface timing information */
        s32Ret = HI_MPI_VO_SetUserIntfSyncInfo(VoDev, &stUserInfo);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

        /* Enable video output device */
        s32Ret = HI_MPI_VO_Enable(VoDev);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

        return s32Ret;
    }

    HI_S32 SAMPLE_COMM_VO_StartChn_MIPI(VO_LAYER VoLayer, SAMPLE_VO_MODE_E enMode)
    {
        HI_S32 i;
        HI_S32 s32Ret = HI_SUCCESS;
        HI_U32 u32WndNum = 0;
        HI_U32 u32Square = 0;
        HI_U32 u32Row = 0;
        HI_U32 u32Col = 0;
        HI_U32 u32Width = 0;
        HI_U32 u32Height = 0;
        VO_CHN_ATTR_S         stChnAttr;
        VO_VIDEO_LAYER_ATTR_S stLayerAttr;

        switch (enMode)
        {
        case VO_MODE_1MUX:
            u32WndNum = 1;
            u32Square = 1;
            break;
        case VO_MODE_2MUX:
            u32WndNum = 2;
            u32Square = 2;
            break;
        case VO_MODE_4MUX:
            u32WndNum = 4;
            u32Square = 2;
            break;
        case VO_MODE_8MUX:
            u32WndNum = 8;
            u32Square = 3;
            break;
        case VO_MODE_9MUX:
            u32WndNum = 9;
            u32Square = 3;
            break;
        case VO_MODE_16MUX:
            u32WndNum = 16;
            u32Square = 4;
            break;
        case VO_MODE_25MUX:
            u32WndNum = 25;
            u32Square = 5;
            break;
        case VO_MODE_36MUX:
            u32WndNum = 36;
            u32Square = 6;
            break;
        case VO_MODE_49MUX:
            u32WndNum = 49;
            u32Square = 7;
            break;
        case VO_MODE_64MUX:
            u32WndNum = 64;
            u32Square = 8;
            break;
        case VO_MODE_2X4:
            u32WndNum = 8;
            u32Square = 3;
            u32Row = 4;
            u32Col = 2;
            break;
        default:
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

        /* Get video layer properties */
        s32Ret = HI_MPI_VO_GetVideoLayerAttr(VoLayer, &stLayerAttr);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
        u32Width = stLayerAttr.stImageSize.u32Width;
        u32Height = stLayerAttr.stImageSize.u32Height;
        SAMPLE_PRT("u32Width:%d, u32Height:%d, u32Square:%d\n", u32Width, u32Height, u32Square);
        for (i = 0; i < u32WndNum; i++)
        {
            if (enMode == VO_MODE_1MUX ||
                enMode == VO_MODE_2MUX ||
                enMode == VO_MODE_4MUX ||
                enMode == VO_MODE_8MUX ||
                enMode == VO_MODE_9MUX ||
                enMode == VO_MODE_16MUX ||
                enMode == VO_MODE_25MUX ||
                enMode == VO_MODE_36MUX ||
                enMode == VO_MODE_49MUX ||
                enMode == VO_MODE_64MUX)
            {
                stChnAttr.stRect.s32X = ALIGN_DOWN((u32Width / u32Square) * (i % u32Square), 2);
                stChnAttr.stRect.s32Y = ALIGN_DOWN((u32Height / u32Square) * (i / u32Square), 2);
                stChnAttr.stRect.u32Width = ALIGN_DOWN(u32Width / u32Square, 2);
                stChnAttr.stRect.u32Height = ALIGN_DOWN(u32Height / u32Square, 2);
                stChnAttr.u32Priority = 0;
                stChnAttr.bDeflicker = HI_FALSE;
            }
            else if (enMode == VO_MODE_2X4)
            {
                stChnAttr.stRect.s32X = ALIGN_DOWN((u32Width / u32Col) * (i % u32Col), 2);
                stChnAttr.stRect.s32Y = ALIGN_DOWN((u32Height / u32Row) * (i / u32Col), 2);
                stChnAttr.stRect.u32Width = ALIGN_DOWN(u32Width / u32Col, 2);
                stChnAttr.stRect.u32Height = ALIGN_DOWN(u32Height / u32Row, 2);
                stChnAttr.u32Priority = 0;
                stChnAttr.bDeflicker = HI_FALSE;
            }

            /* Set properties for the specified video output channel */
            s32Ret = HI_MPI_VO_SetChnAttr(VoLayer, i, &stChnAttr);
            if (s32Ret != HI_SUCCESS)
            {
                printf("%s(%d):failed with %#x!\n", \
                    __FUNCTION__, __LINE__, s32Ret);
                return HI_FAILURE;
            }

            /* Set video output channel rotation angle */
            s32Ret = HI_MPI_VO_SetChnRotation(VoLayer, i, ROTATION_90);
            if (s32Ret != HI_SUCCESS)
            {
                printf("%s(%d):failed with %#x!\n", \
                    __FUNCTION__, __LINE__, s32Ret);
                return HI_FAILURE;
            }

            /* Enables the specified video output channel */
            s32Ret = HI_MPI_VO_EnableChn(VoLayer, i);
            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("failed with %#x!\n", s32Ret);
                return HI_FAILURE;
            }
        }

        return HI_SUCCESS;
    }

    /* start vo to mipi lcd */
    HI_S32 SAMPLE_COMM_VO_StartVO_MIPI(SAMPLE_VO_CONFIG_S* pstVoConfig)
    {
        RECT_S                 stDefDispRect = { 0, 0, 800, 480 };
        SIZE_S                 stDefImageSize = { 800, 480 };

        /*******************************************
        * VO device VoDev# information declaration.
        ********************************************/
        VO_DEV                 VoDev = 0;
        VO_LAYER               VoLayer = 0;
        SAMPLE_VO_MODE_E       enVoMode = 0;
        VO_INTF_TYPE_E         enVoIntfType = VO_INTF_HDMI;
        VO_PART_MODE_E         enVoPartMode = VO_PART_MODE_SINGLE;
        VO_PUB_ATTR_S          stVoPubAttr = { 0 };
        VO_VIDEO_LAYER_ATTR_S  stLayerAttr = { 0 };
        VO_CSC_S               stVideoCSC = { 0 };
        HI_S32                 s32Ret = HI_SUCCESS;

        if (NULL == pstVoConfig)
        {
            SAMPLE_PRT("Error:argument can not be NULL\n");
            return HI_FAILURE;
        }
        VoDev = pstVoConfig->VoDev;
        VoLayer = pstVoConfig->VoDev;
        enVoMode = pstVoConfig->enVoMode;
        enVoIntfType = pstVoConfig->enVoIntfType;
        enVoPartMode = pstVoConfig->enVoPartMode;

        /********************************
        * Set and start VO device VoDev#.
        *********************************/
        stVoPubAttr.enIntfType = VO_INTF_MIPI;
        stVoPubAttr.enIntfSync = VO_OUTPUT_USER;
        stVoPubAttr.stSyncInfo.bSynm = 0;
        stVoPubAttr.stSyncInfo.bIop = 1;
        stVoPubAttr.stSyncInfo.u8Intfb = 0;

        stVoPubAttr.stSyncInfo.u16Hmid = 1;
        stVoPubAttr.stSyncInfo.u16Bvact = 1;
        stVoPubAttr.stSyncInfo.u16Bvbb = 1;
        stVoPubAttr.stSyncInfo.u16Bvfb = 1;

        stVoPubAttr.stSyncInfo.bIdv = 0;
        stVoPubAttr.stSyncInfo.bIhs = 0;
        stVoPubAttr.stSyncInfo.bIvs = 0;

        stVoPubAttr.stSyncInfo.u16Hact = 480;
        stVoPubAttr.stSyncInfo.u16Hbb = 60;
        stVoPubAttr.stSyncInfo.u16Hfb = 50;
        stVoPubAttr.stSyncInfo.u16Hpw = 10;
        stVoPubAttr.stSyncInfo.u16Vact = 800;
        stVoPubAttr.stSyncInfo.u16Vbb = 24;
        stVoPubAttr.stSyncInfo.u16Vfb = 20;
        stVoPubAttr.stSyncInfo.u16Vpw = 4;
        stVoPubAttr.u32BgColor = pstVoConfig->u32BgColor;

        s32Ret = SAMPLE_COMM_VO_StartDev_MIPI(VoDev, &stVoPubAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VO_StartDev_MIPI failed!\n");
            return s32Ret;
        }

        /******************************
        * Set and start layer VoDev#.
        ********************************/

        s32Ret = SAMPLE_COMM_VO_GetWH_MIPI(stVoPubAttr.enIntfSync,
            &stLayerAttr.stDispRect.u32Width, &stLayerAttr.stDispRect.u32Height,
            &stLayerAttr.u32DispFrmRt);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VO_GetWH_MIPI failed!\n");
            SAMPLE_COMM_VO_StopDev(VoDev);
            return s32Ret;
        }
        stLayerAttr.bClusterMode = HI_FALSE;
        stLayerAttr.bDoubleFrame = HI_FALSE;
        stLayerAttr.enPixFormat = pstVoConfig->enPixFormat;

        stLayerAttr.stDispRect.s32X = 0;
        stLayerAttr.stDispRect.s32Y = 0;

        /******************************
        Set display rectangle if changed.
        ********************************/
        if (0 != memcmp(&pstVoConfig->stDispRect, &stDefDispRect, sizeof(RECT_S)))
        {
            memcpy(&stLayerAttr.stDispRect, &pstVoConfig->stDispRect, sizeof(RECT_S));
        }

        /******************************
        Set image size if changed.
        ********************************/
        if (0 != memcmp(&pstVoConfig->stImageSize, &stDefImageSize, sizeof(SIZE_S)))
        {
            memcpy(&stLayerAttr.stImageSize, &pstVoConfig->stImageSize, sizeof(SIZE_S));
        }
        stLayerAttr.stImageSize.u32Width = stLayerAttr.stDispRect.u32Width = 480;
        stLayerAttr.stImageSize.u32Height = stLayerAttr.stDispRect.u32Height = 800;
        stLayerAttr.enDstDynamicRange = pstVoConfig->enDstDynamicRange;

        if (pstVoConfig->u32DisBufLen)
        {
            /* Set buffer length */
            s32Ret = HI_MPI_VO_SetDisplayBufLen(VoLayer, pstVoConfig->u32DisBufLen);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VO_SetDisplayBufLen failed with %#x!\n", s32Ret);
                SAMPLE_COMM_VO_StopDev(VoDev);
                return s32Ret;
            }
        }
        if (VO_PART_MODE_MULTI == enVoPartMode)
        {
            /* Set the segmentation mode of the video layer */
            s32Ret = HI_MPI_VO_SetVideoLayerPartitionMode(VoLayer, enVoPartMode);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VO_SetVideoLayerPartitionMode failed!\n");
                SAMPLE_COMM_VO_StopDev(VoDev);
                return s32Ret;
            }
        }

        /* start layer */
        s32Ret = SAMPLE_COMM_VO_StartLayer(VoLayer, &stLayerAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VO_Start video layer failed!\n");
            SAMPLE_COMM_VO_StopDev(VoDev);
            return s32Ret;
        }

        if (VO_INTF_MIPI == enVoIntfType)
        {
            /*get video layerCSC*/
            s32Ret = HI_MPI_VO_GetVideoLayerCSC(VoLayer, &stVideoCSC);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VO_GetVideoLayerCSC failed!\n");
                SAMPLE_COMM_VO_StopDev(VoDev);
                return s32Ret;
            }
            stVideoCSC.enCscMatrix = VO_CSC_MATRIX_BT709_TO_RGB_PC;
            /* Set video layer CSC*/
            s32Ret = HI_MPI_VO_SetVideoLayerCSC(VoLayer, &stVideoCSC);
            if (HI_SUCCESS != s32Ret)
            {
                SAMPLE_PRT("HI_MPI_VO_SetVideoLayerCSC failed!\n");
                SAMPLE_COMM_VO_StopDev(VoDev);
                return s32Ret;
            }
        }

        /******************************
        * start vo channels.
        ********************************/
        s32Ret = SAMPLE_COMM_VO_StartChn_MIPI(VoLayer, enVoMode);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VO_StartChn failed!\n");
            SAMPLE_COMM_VO_StopLayer(VoLayer);
            SAMPLE_COMM_VO_StopDev(VoDev);
            return s32Ret;
        }

        return HI_SUCCESS;
    }

    HI_S32 SAMPLE_COMM_REGION_Hide(HI_S32 Handle, MPP_CHN_S* pstChn)
    {
        HI_S32 s32Ret;
        RGN_CHN_ATTR_S pstChnAttr;

        if (HI_NULL == pstChn)
        {
            SAMPLE_PRT("pstChn is NULL !\n");
            return HI_FAILURE;
        }
        SAMPLE_REGION_GetDisplayAttr(Handle, pstChn, &pstChnAttr);
        pstChnAttr.bShow = HI_FALSE; //hide

        SAMPLE_REGION_SetDisplayAttr(Handle, pstChn, &pstChnAttr);

        s32Ret = SAMPLE_REGION_AttachToChn(Handle, pstChn, &pstChnAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_REGION_AttachToChn failed!\n");
        }
        /*detach region from chn */
        if (HI_SUCCESS != s32Ret)
        {
            s32Ret = SAMPLE_REGION_DetachFromChn(Handle, pstChn);
        }
        return s32Ret;
    }
    HI_S32 SAMPLE_COMM_REGION_Show(HI_S32 Handle, MPP_CHN_S* pstChn)
    {
        HI_S32 s32Ret;
        RGN_CHN_ATTR_S pstChnAttr;

        if (HI_NULL == pstChn)
        {
            SAMPLE_PRT("pstChn is NULL !\n");
            return HI_FAILURE;
        }
        SAMPLE_REGION_GetDisplayAttr(Handle, pstChn, &pstChnAttr);
        pstChnAttr.bShow = HI_TRUE; //show

        SAMPLE_REGION_SetDisplayAttr(Handle, pstChn, &pstChnAttr);

        s32Ret = SAMPLE_REGION_AttachToChn(Handle, pstChn, &pstChnAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_REGION_AttachToChn failed!\n");
        }
        /*detach region from chn */
        if (HI_SUCCESS != s32Ret)
        {
            s32Ret = SAMPLE_REGION_DetachFromChn(Handle, pstChn);
        }
        return s32Ret;
    }

    /* 创建region,将region加入通道,实现菜单 */
    HI_S32 SAMPLE_REGION_VI_VPSS_VO(HI_S32 HandleNum, RGN_TYPE_E enType, MPP_CHN_S* pstChn)
    {
        HI_S32         s32Ret;

        //创建Region
        s32Ret = SAMPLE_COMM_REGION_Create(HandleNum, enType);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_Create failed!\n");
            goto EXIT1;
        }
        if (HI_SUCCESS == s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_Create success!\n");
        }

        //将创建的region加入到通道中
        s32Ret = SAMPLE_COMM_REGION_AttachToChn(HandleNum, enType, pstChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_AttachToChn failed!\n");
            goto EXIT2;
        }
        if (HI_SUCCESS == s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_AttachToChn success!\n");
        }

        Look(menu, menu_num, REGION_1, pstChn);
        Look(menu, menu_num, REGION_1, pstChn);
        Look(menu, menu_num, REGION_1, pstChn);
        Look(menu, menu_num, REGION_1, pstChn);
        Look(menu, menu_num, REGION_1, pstChn);//Look确保菜单的位置是正确的
        gpio(pstChn); //按键控制菜单

        PAUSE();
    EXIT2:
        s32Ret = SAMPLE_COMM_REGION_DetachFrmChn(HandleNum, enType, pstChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_AttachToChn failed!\n");
        }
    EXIT1:
        s32Ret = SAMPLE_COMM_REGION_Destroy(HandleNum, enType);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_REGION_AttachToChn failed!\n");
        }

        return s32Ret;
    }

    /*
        Display the data collected by sensor to LCD screen
        VI->VPSS->VO->MIPI
    */
    HI_S32 SAMPLE_VIO_VPSS_VO_MIPI(HI_VOID)
    {
        HI_S32             HandleNum;
        RGN_TYPE_E         enType;
        MPP_CHN_S          stChn;
        HandleNum = 8; 
        enType = OVERLAYEX_RGN;
        stChn.enModId = HI_ID_VPSS;
        stChn.s32DevId = 0;
        stChn.s32ChnId = 0;


        HI_S32             s32Ret = HI_SUCCESS;
        HI_S32             fd = 0;
        HI_S32             s32ViCnt = 1;
        VI_DEV             ViDev = 0;
        VI_PIPE            ViPipe = 0;
        VI_CHN             ViChn = 0;
        HI_S32             s32WorkSnsId = 0;
        SAMPLE_VI_CONFIG_S stViConfig;

        SIZE_S             stSize;
        VB_CONFIG_S        stVbConf;
        PIC_SIZE_E         enPicSize;
        HI_U32             u32BlkSize;

        VO_CHN             VoChn = 0;
        SAMPLE_VO_CONFIG_S stVoConfig;

        WDR_MODE_E         enWDRMode = WDR_MODE_NONE;
        DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;
        PIXEL_FORMAT_E     enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        VIDEO_FORMAT_E     enVideoFormat = VIDEO_FORMAT_LINEAR;
        COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;
        VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;//vi online vpss offlie

        VPSS_GRP           VpssGrp = 0;
        VPSS_GRP_ATTR_S    stVpssGrpAttr; //group属性
        VPSS_CHN           VpssChn = VPSS_CHN0; //channe0

        HI_BOOL            abChnEnable[VPSS_MAX_PHY_CHN_NUM] = { 0 };//channel使能
        VPSS_CHN_ATTR_S    astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM];

        /* config vi */
        SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);

        stViConfig.s32WorkingViNum = s32ViCnt;
        stViConfig.as32WorkingViId[0] = 0;
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev = ViDev;
        stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId = 0;
        stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev = ViDev;
        stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode = enWDRMode;
        stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = enMastPipeMode;
        stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0] = ViPipe;
        stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1] = -1;
        stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[2] = -1;
        stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[3] = -1;
        stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn = ViChn;
        stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat = enPixFormat;
        stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange = enDynamicRange;
        stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat = enVideoFormat;
        stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode = enCompressMode;

        /* get picture size */
        s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size by sensor failed!\n");
            return s32Ret;
        }

        /* get picture size(w*h), according enPicSize */
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("get picture size failed!\n");
            return s32Ret;
        }

        /* config vb */
        memset_s(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
        stVbConf.u32MaxPoolCnt = 2; //视频缓存


        // get picture buffer size
        u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
        stVbConf.astCommPool[0].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[0].u32BlkCnt = 10;

        //get raw buffer size
        u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
        stVbConf.astCommPool[1].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[1].u32BlkCnt = 4;


        /* vb init & MPI system init */
        s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("system init failed with %d!\n", s32Ret);
            return s32Ret;
        }

        /* set VO config to mipi, get mipi device */
        s32Ret = SAMPLE_VO_CONFIG_MIPI(&fd);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("CONFIG MIPI failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }
        /* start vi */
        s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("start vi failed.s32Ret:0x%x !\n", s32Ret);
            goto EXIT;
        }

        /* config vpss */
        memset_s(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssGrpAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
        stVpssGrpAttr.enPixelFormat = enPixFormat;
        stVpssGrpAttr.u32MaxW = stSize.u32Width;
        stVpssGrpAttr.u32MaxH = stSize.u32Height;
        stVpssGrpAttr.bNrEn = HI_TRUE;
        stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;
        stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;

        astVpssChnAttr[VpssChn].u32Width = stSize.u32Width;
        astVpssChnAttr[VpssChn].u32Height = stSize.u32Height;
        astVpssChnAttr[VpssChn].enChnMode = VPSS_CHN_MODE_USER;
        astVpssChnAttr[VpssChn].enCompressMode = enCompressMode;
        astVpssChnAttr[VpssChn].enDynamicRange = enDynamicRange;
        astVpssChnAttr[VpssChn].enVideoFormat = enVideoFormat;
        astVpssChnAttr[VpssChn].enPixelFormat = enPixFormat;
        astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = 30;
        astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = 30;
        astVpssChnAttr[VpssChn].u32Depth = 0;
        //astVpssChnAttr[VpssChn].u32Depth = 1; //change
        astVpssChnAttr[VpssChn].bMirror = HI_FALSE;
        astVpssChnAttr[VpssChn].bFlip = HI_FALSE;
        astVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_NONE;
        printf("channel:width:%d,Height:%d\n",stSize.u32Width,stSize.u32Height);

        /* start vpss */
        abChnEnable[VpssChn] = HI_TRUE;//启动channel 0（channel 0只能缩小不能放大）
        s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("start vpss group failed. s32Ret: 0x%x !\n", s32Ret);
            goto EXIT1;
        }


        /* vpss bind vo */
        s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("vpss bind vi failed. s32Ret: 0x%x !\n", s32Ret);
            goto EXIT2;
        }

        /* config vo */
        SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
        stVoConfig.enDstDynamicRange = enDynamicRange;

        stVoConfig.enVoIntfType = VO_INTF_MIPI; /* set VO int type */
        stVoConfig.enIntfSync = VO_OUTPUT_USER; /* set VO output information */

        stVoConfig.enPicSize = enPicSize;

        /* start vo */
        s32Ret = SAMPLE_COMM_VO_StartVO_MIPI(&stVoConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("start vo failed. s32Ret: 0x%x !\n", s32Ret);
            goto EXIT3;
        }

        /* vpss bind vo */
        s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret);
            goto EXIT4;
        }

        s32Ret = SAMPLE_REGION_VI_VPSS_VO(HandleNum, enType, &stChn);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_REGION_VI_VPSS_VO failed. s32Ret: 0x%x !\n", s32Ret);
            goto EXIT;
        }

        PAUSE();

        SAMPLE_COMM_VPSS_UnBind_VO(VpssGrp, VpssChn, stVoConfig.VoDev, VoChn);
        SAMPLE_VO_DISABLE_MIPITx(fd);
        SAMPLE_CLOSE_MIPITx_FD(fd);
        system("echo 0 > /sys/class/gpio/gpio55/value");


    EXIT4:
        SAMPLE_COMM_VO_StopVO(&stVoConfig);
    EXIT3:
        SAMPLE_COMM_VI_UnBind_VPSS(ViPipe, ViChn, VpssGrp);
    EXIT2:
        SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable);
    EXIT1:
        SAMPLE_COMM_VI_StopVi(&stViConfig);
    EXIT:
        SAMPLE_COMM_SYS_Exit();
        return s32Ret;
    }

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

